﻿using CgdataBase;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CgdataBase
{
    public class AppSettings : ApplicationSettings
    {
        #region 基础方法

        private static AppSettings _instance;
        public static AppSettings Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new AppSettings();
                }

                return _instance;
            }
        }

        private string _path;

        public void Init(string path)
        {
            _path = path;
            Init();
        }

        public void Init(bool portable)
        {
            if (portable)
            {
                Init(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "config.ini"));
            }
            else
            {
                string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
                string appDataPath = ConfigController.GetAppDataPath(assemblyName);
                Init(Path.Combine(appDataPath, "config.ini"));
            }
        }

        public override Hashtable LoadSettings()
        {
            try
            {
                string fileName = _path;

                if (File.Exists(fileName))
                {
                    string json = File.ReadAllText(fileName, Encoding.UTF8);
                    return JsonConvert.DeserializeObject<Hashtable>(json) ?? new Hashtable();
                }
            }
            catch (Exception)
            {
                Debug.Assert(false);
            }

            return new Hashtable();
        }

        public override void SaveSettings(Hashtable appConfig)
        {
            string fileName = _path;

            if (appConfig == null)
                appConfig = new Hashtable();

            foreach (PropertyInfo prop in this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(s => s.CanWrite))
            {
                if (appConfig.ContainsKey(prop.Name) == false)
                {
                    appConfig.Add(prop.Name, prop.GetValue(this));
                }
            }

            FileSystemHelper.TryCreateDirectory(Path.GetDirectoryName(fileName));
            string json = JsonConvert.SerializeObject(appConfig, Formatting.Indented);
            File.WriteAllText(fileName, json);
        }

        /// <summary>
        /// 添加或更新指定配置信息的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool AddOrUpdateValue(Type type, string key, object value, bool autoSave = false)
        {
            var mykey = string.Format("{0}.{1}", type, key);
            var isChange = AddOrUpdateValue(mykey, value);
            if (isChange && autoSave)
            {
                Save();
            }

            return isChange;
        }

        /// <summary>
        /// 获取指定配置信息的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public T GetValueOrDefault<T>(Type type, string key, T defaultValue)
        {
            var mykey = string.Format("{0}.{1}", type, key);
            return GetValueOrDefault<T>(mykey, defaultValue);
        }

        #endregion 基础方法

        public bool OfflineMode
        {
            get
            {
                return GetValueOrDefault<bool>(nameof(OfflineMode), true);
            }
            set
            {
                if (AddOrUpdateValue(nameof(OfflineMode), value))
                {
                    Save();
                }
            }
        }

        public FreeSql.DataType DatabaseType
        {
            get
            {
                return GetValueOrDefault<FreeSql.DataType>(nameof(DatabaseType), FreeSql.DataType.Sqlite);
            }
            set
            {
                if (AddOrUpdateValue(nameof(DatabaseType), value))
                {
                    Save();
                }
            }
        }

        public string DatabaseConnectionString
        {
            get
            {
                return GetValueOrDefault<string>(nameof(DatabaseConnectionString), "Data Source=database.db; Pooling=true;Min Pool Size=1");
            }
            set
            {
                if (AddOrUpdateValue(nameof(DatabaseConnectionString), value))
                {
                    Save();
                }
            }
        }

        public bool UseAutoSyncStructure
        {
            get
            {
                return GetValueOrDefault<bool>(nameof(UseAutoSyncStructure), true);
            }
            set
            {
                if (AddOrUpdateValue(nameof(UseAutoSyncStructure), value))
                {
                    Save();
                }
            }
        }

        public int FontSize
        {
            get
            {
                return GetValueOrDefault<int>(nameof(FontSize), 16);
            }
            set
            {
                if (AddOrUpdateValue(nameof(FontSize), value))
                {
                    Save();
                }
            }
        }

        public string FontName
        {
            get
            {
                return GetValueOrDefault<string>(nameof(FontName), "方正屏显雅宋简体,微软雅黑,宋体");
            }
            set
            {
                if (AddOrUpdateValue(nameof(FontName), value))
                {
                    Save();
                }
            }
        }

        public string IgnoreFolder
        {
            get
            {
                return GetValueOrDefault<string>(nameof(IgnoreFolder), "");
            }
            set
            {
                if (AddOrUpdateValue(nameof(IgnoreFolder), value))
                {
                    Save();
                }
            }
        }

        public string IgnoreFile
        {
            get
            {
                return GetValueOrDefault<string>(nameof(IgnoreFile), "");
            }
            set
            {
                if (AddOrUpdateValue(nameof(IgnoreFile), value))
                {
                    Save();
                }
            }
        }

        public string RecursiveIgnoreFolder
        {
            get
            {
                return GetValueOrDefault<string>(nameof(RecursiveIgnoreFolder), "bin\r\nobj\r\n.vs\r\n.idea\r\npackages");
            }
            set
            {
                if (AddOrUpdateValue(nameof(RecursiveIgnoreFolder), value))
                {
                    Save();
                }
            }
        }

        public string RecursiveIgnoreFile
        {
            get
            {
                return GetValueOrDefault<string>(nameof(RecursiveIgnoreFile), "");
            }
            set
            {
                if (AddOrUpdateValue(nameof(RecursiveIgnoreFile), value))
                {
                    Save();
                }
            }
        }

        public string FullCopyFolder
        {
            get
            {
                return GetValueOrDefault<string>(nameof(FullCopyFolder), ".git");
            }
            set
            {
                if (AddOrUpdateValue(nameof(FullCopyFolder), value))
                {
                    Save();
                }
            }
        }

        public bool Topmost
        {
            get
            {
                return GetValueOrDefault<bool>(nameof(Topmost), false);
            }
            set
            {
                if (AddOrUpdateValue(nameof(Topmost), value))
                {
                    Save();
                }
            }
        }
    }
}